package dse;

import dse.messages.*;

public interface ExperimentRecorder {
	
	/**
	 * This constant can be used with the methods in this interface that take
	 * timeLeft values.  These values indicate the amount of time left in the
	 * current period when the event the method reports took place.  Passing 
	 * PeriodStart to these methods indicates that the event takes place at the
	 * very beginning of the current period.  
	 */
	public static final double PeriodStart = -1.0;
	public static final boolean debug = false;
	
	
	/**
	 * Called whenever a bloom filter update has started.
	 * 
	 * @param id
	 * @param requester
	 * @param target
	 * @param timeLeft
	 */
	void bloomFilterRefreshInitiated(
			int id,
			Node requester, 
			Node target, 
			double timeLeft
			);
	/**
	 * Called whenever a bloom filter update has finished successfully or 
	 * failed.
	 * 
	 * @param id
	 * @param requester
	 * @param target
	 * @param success
	 * @param timeLeft
	 */
	void bloomFilterRefreshFinished(
			int id,
			Node requester, 
			Node target, 
			boolean success, 
			double timeLeft
			);
	/**
	 * Called whenever the Message processes method simulates the transfer of 
	 * bytes. 
	 * 
	 * @param id
	 * @param messageType
	 * @param purpose TODO
	 * @param distance
	 * @param bytes
	 */
	void bytesSent (
			int id, MessageType messageType, MessagePurpose purpose, double distance, long bytes
			);
	/**
	 * Called whenever the Message processes method simulates the transfer of 
	 * bytes. 
	 * 
	 * @param id
	 * @param messageType
	 * @param purpose TODO
	 * @param distance
	 * @param bytes
	 * @param bytesRemaining
	 */
	void bytesSent (
			int id, MessageType messageType, MessagePurpose purpose, double distance,
			long bytes, long bytesRemaining
			);
	/**
	 * Called when a cache request has finished.
	 * 
	 * @param id
	 * @param requester
	 * @param object
	 * @param sharesCached TODO
	 * @param success
	 * @param timeLeft
	 */
	void cacheRequestFinished (
			int id, 
			Node requester, 
			DataObject object, 
			int sharesCached,
			boolean success, double timeLeft
			);
	/**
	 * Called when a cache request is initiated.
	 * @param id
	 * @param requester
	 * @param object
	 * @param timeLeft
	 */
	void cacheRequestInitiated (
			int id,
			Node requester, 
			DataObject object, 
			double timeLeft
			);
	/**
	 * Called when a data object request has finished.
	 * 
	 * @param id
	 * @param requester
	 * @param object
	 * @param success
	 * @param foundInOrNear The node the data object was found in, or the super
	 * 						node of the cluster it was found in.
	 * @param wasCached		Whether or not the data object was found cached.
	 * @param timeLeft
	 */
	void dataRequestFinished (
			int id, 
			Node requester, 
			DataObject object, 
			boolean success, 
			Node foundInOrNear,
			boolean wasCached,
			double timeLeft
			);
	void OneRoundInMoreFinished (int id, double time);	
	/**
	 * Called when a data object request is initiated.
	 * @param id
	 * @param requester
	 * @param object
	 * @param timeLeft
	 */
	void dataRequestInitiated (
			int id,
			Node requester, 
			DataObject object, 
			double timeLeft
			);
	/**
	 * Called when a data object update has finished.
	 * 
	 * @param id
	 * @param requester
	 * @param object
	 * @param success
	 * @param foundInOrNear The node the data object was found in, or the super
	 * 						node of the cluster it was found in.
	 * @param wasCached		Whether or not the data object was found cached.
	 * @param timeLeft
	 */
	void dataUpdateFinished (
			int id, 
			Node requester, 
			DataObject object, 
			boolean success, 
			double timeLeft
			);
	/**
	 * Called when a data object update is initiated.
	 * @param id
	 * @param requester
	 * @param object
	 * @param timeLeft
	 */
	void dataUpdateInitiated (
			int id,
			Node requester, 
			DataObject object, 
			double timeLeft
			);
	/**
	 * Records a debug message during a time period (where timeLeft can be used
	 * to calculate exactly when the message occurs).
	 * 
	 * @param object
	 * @param message
	 * @param timeLeft
	 */
	void debug (Object object, String message, double timeLeft);
	/**
	 * Records some (debug) information.
	 * 
	 * @param message
	 */
	void debug (String message);
	/**
	 * This should get a results object containing all information about the
	 * experiment that was run.
	 * 
	 * @return
	 */
	ExperimentResults getResults ();
	/**
	 * Called every period where a message is processed.
	 * 
	 * @param id
	 * @param messageType
	 */
	void messageProcessed (int id, MessageType messageType);
	/**
	 * When a message has been started, but was not accepted by the receiver.
	 * 
	 * @param id
	 * @param messageType
	 * @param timeLeft TODO
	 */
	void messageTransferCancelled (
			int id, MessageType messageType, double timeLeft
			);
	/**
	 * When a message has been started and is now finished.
	 * 
	 * @param id
	 * @param messageType
	 * @param timeLeft TODO
	 */
	void messageTransferFinished (
			int id, MessageType messageType, double timeLeft
			);
	/**
	 * Called when a message has started but has been stopped because one of the
	 * two nodes has gone down.
	 * 
	 * @param id
	 * @param messageType
	 * @param timeLeft 
	 */
	void messageTransferInterupted (
			int id, MessageType messageType, double timeLeft
			);
	/**
	 * Called when a message transfer has started.
	 * 
	 * @param id
	 * @param messageType
	 * @param distance
	 * @param size
	 * @param timeLeft
	 */
	void messageTransferStarted (
			int id, 
			MessageType messageType, 
			double distance, 
			long size,
			double timeLeft
			);
	/**
	 * Informs the recorder that the next period has started.
	 * 
	 * @param startsAt	When the period starts in seconds.
	 * @param length	Length of the time period in seconds.
	 */
	void nextPeriod (double startsAt, double length);
	/**
	 * Called when a data object share could not be looked up.  Though it still
	 * may be successfully found later.
	 */
	void shareLookupFailed ();
	/**
	 * Called when a data object share is successfully looked up.
	 */
	void shareLookupSuccessful ();
	/**
	 * Called when an update super node with recent requests transaction is
	 * finished.
	 * 
	 * @param id
	 * @param sender
	 * @param superNode
	 * @param success
	 * @param timeLeft
	 */
	void updateSuperNodeWithRequestsFinished (
			int id, Node sender, Node superNode, boolean success, 
			double timeLeft
			);
	/**
	 * Called when an update super node with recent requests transaction is
	 * started.
	 * 
	 * @param id
	 * @param sender
	 * @param superNode
	 * @param timeLeft
	 */
	void updateSuperNodeWithRequestsInitiated (
			int id, Node sender, Node superNode, double timeLeft
			);
	
	
	/**
	 * Reports a warning.
	 * 
	 * @param message
	 */
	void warn (String message);
	
	void requestMoreShares(DataObject dobj, boolean val);
	void requestPreviousShares(DataObject dobj, boolean val);
	void readDuration(double dur);
	void updateDuration(double dur);
	
	void shareHistorySize(int size);
	
	//two level propagation
	void dataUpdatePropagationInitiated (
			int id,
			Node requester, 
			DataObject object, 
			double timeLeft
			);
	void dataUpdatePropagationFinished (
			int id, 
			Node requester, 
			DataObject object, 
			double timeLeft
			);
	
	void svrFinished (
			int id, 
			Node requester, 
			DataObject object,
			double time
			);
	void svrInitiated (
			int id,
			Node requester, 
			DataObject object, 
			double time
			);
	void setExperiment(Experiment exp);
}
